import { gkhCreate, removeItemInArray } from './tools';
import GkhTableTemplate from './TableTemplate';

/**
 * 文本显示框  绘制表格的时候可以编辑文字  编辑模式和查看模式只能显示绘制表格编辑的文字，且不能修改
 * @param {*} attribute 属性
 * @param {*} mode @default 3 模式：1：绘制模式、2：编辑模式、3：查看模式 
 * @param {*} template 父级模板  目前只有表单模板和盒子模板
 */
function TextShow(attribute = {}, mode = 3, template) {
  const me = this;
  this.type = 1;
  this.parentContainer = template;
  attribute.type = 1;
  this.attrData = attribute;
  const { text } = attribute;
  const container = gkhCreate('div', {
    className: 'gkh_text_div',
    innerText: mode != 1 ? text : undefined
  });
  let content;
  let input;
  let value;
  let height;
  let preHeight;
  function change(event) {
    preHeight = container.offsetHeight;
    if (mode == 1 && value !== input.value) {
      value = input.value;
      content.innerText = value;
      me.attrData.text = value;
      height = container.offsetHeight - preHeight;
      if (height && template && template.cellHeightChange) {
        template.cellHeightChange(container, height - preHeight);
      }
    }
  }
  if (mode == 1) {
    content = gkhCreate('div', {
      target: container,
      className: 'gkh-text-height-adujst'
    });
    input = gkhCreate('textarea', {
      target: container,
      innerText: text,
      listeners: {
        keyup: change,
        change
      }
    });
  }

  this.remove = () => { };
  this.setDisabled = (arg) => { };
  this.setVisible = (arg) => { };
  this.setReadonly = (arg) => { };
  this.getAttrData = function () {
    return me.attrData;
  }
  this.render = () => {
    return container;
  };
  this.renderAfter = () => {
    change();
  }
}

// 文本输入框
function Textarea(attribute = {}, mode = 3, template) {
  const me = this;
  this.type = 2;
  attribute.type = 2;
  this.attrData = attribute;
  this.parentContainer = template;
  const { placeholder = '', defaultValue = '', disabled = false, readonly = false, fieldName } = attribute;
  const container = gkhCreate('div', {
    className: 'gkh_text_div',
    innerText: mode === 3 ? defaultValue : '',
  });
  let content;
  let input;
  let value = defaultValue;
  let height;
  let preHeight;
  function change() {
    preHeight = container.offsetHeight;
    if (mode == 2 && value !== input.value) {
      value = input.value;
      content.innerText = value;
      height = container.offsetHeight - preHeight;
      if (height && template && template.cellHeightChange) {
        template.cellHeightChange(container, height - preHeight);
      }
    }
  }
  if (mode == 2) {
    content = gkhCreate('div', {
      target: container,
      className: 'gkh-text-height-adujst'
    });
    input = gkhCreate('textarea', {
      target: container,
      innerText: defaultValue,
      // attribute: { placeholder, disabled, readonly }
    });
    input.onkeyup = change;
    input.onchange = change;
  }

  this.setDisabled = (arg) => {
    input.disabled = arg;
  };
  this.setVisible = (arg) => {
    let visibility = 'string' === typeof arg ? arg : 'hidden';
    if (arg) {
      visibility = 'visible';
    }
    container.style.visibility = visibility;
  };
  this.setReadonly = (arg) => { };
  this.getValue = () => value;
  this.setValue = (arg) => {
    if (mode == 2) {
      input.value = arg;
      change();
    } else {
      container.innerText = arg;
    }
  };
  this.reset = () => { me.setValue(defaultValue) };
  this.getAttrData = function () {
    return me.attrData;
  }
  const fieldNameChange = (arg) => {
    me.attrData.fieldName = arg.target.value;
  }
  this.render = () => {
    if (mode == 1) {
      gkhCreate('div', {
        target: container,
        className: 'gkh-fieldname-div',
        childs: [
          gkhCreate('label', { innerText: '字段名：' }),
          gkhCreate('input', {
            attribute: { value: fieldName ? fieldName : '' },
            listeners: { change: fieldNameChange },
          })
        ]
      })
    }
    return container;
  };
  this.renderAfter = () => {
    change();
  }
}

// 表格模板
function TableTemplate(attribute = {}, mode = 3, template) {
  const me = this;
  this.type = 3;
  attribute.type = 3;
  if (!attribute.rows) {
    attribute.rows = 3;
  }
  if (!attribute.cols) {
    attribute.cols = 3;
  }
  this.attrData = attribute;
  this.parentContainer = template;
  const container = gkhCreate('div', {
    style: {
      padding: '1px'
    }
  });
  let tableInstance;
  const createTable = (arg) => {
    const inputs = attribDiv.getElementsByTagName('input');
    me.attrData.rows = parseInt(inputs[1].value);
    me.attrData.cols = parseInt(inputs[2].value);
    if (Number.isNaN(me.attrData.rows) || Number.isNaN(me.attrData.cols)) {
      console.error("行数、列数必须是整数");
      return false;
    }
    if (tableInstance) {
      tableInstance.init(me.attrData.rows, me.attrData.cols);
    }
    return false;
  }
  const fieldNameChange = (arg) => {
    me.attrData.fieldName = arg.target.value;
  }
  let attribDiv;
  if (mode == 1) {
    attribDiv = gkhCreate('div', {
      childs: [
        gkhCreate('span', { childs: [gkhCreate('label', { innerText: '字段名：' }), gkhCreate('input', { attribute: { value: me.attrData.fieldName ? me.attrData.fieldName : '' }, listeners: { change: fieldNameChange } })] }),
        gkhCreate('span', { childs: [gkhCreate('label', { innerText: '行：' }), gkhCreate('input', { attribute: { value: me.attrData.rows } })] }),
        gkhCreate('span', { childs: [gkhCreate('label', { innerText: '列：' }), gkhCreate('input', { attribute: { value: me.attrData.cols } })] }),
        gkhCreate('button', { className: 'gkh-button', innerText: '生成表格', listeners: { click: createTable } })
      ]
    });
    container.appendChild(attribDiv);
  }
  this.tableInstance = tableInstance;
  this.getValue = () => {
    if (tableInstance) {
      return tableInstance.getValues();
    }
    return undefined;
  };
  this.setValue = (arg) => {
    if (tableInstance) {
      tableInstance.setValues(arg);
    }
  };
  this.reset = () => {
    if (tableInstance) {
      tableInstance.reset();
    }
  };
  this.getAttrData = function () {
    if (tableInstance) {
      me.attrData.templateData = tableInstance.getTemplateData();
    }
    return me.attrData;
  }
  this.sizeChange = function () {
    if (tableInstance) {
      tableInstance.sizeChange(false);
    }
  }
  this.render = () => {
    return container;
  };
  this.renderAfter = () => {
    if (!tableInstance) {
      tableInstance = new GkhTableTemplate(container, mode);
      me.tableInstance = tableInstance;
    }
    if (attribute.templateData) {
      tableInstance.renderTemplate(attribute.templateData)
    } else {
      tableInstance.init(me.attrData.rows, me.attrData.cols);
    }
    tableInstance.sizeChange();
  }
}

// 新增按钮
function addButton(attribute = {}, mode = 3, template) {
  const me = this;
  this.type = 5;
  attribute.type = 5;
  this.attrData = attribute;
  this.parentContainer = template;
  const { placeholder, defaultValue, disabled, readonly, fieldName, rows, cols } = attribute;
  this.fieldName = fieldName ? fieldName : Math.random().toFixed(4);
  this.attrData.fieldName = this.fieldName;
  let attribDiv;
  let selectedCell;
  let count = 0;
  const container = gkhCreate('div', {
    style: {
      height: 'auto'
    }
  });
  const addDiv = {};
  const fieldNameChange = (arg) => {
    me.attrData.fieldName = arg.target.value;
  }
  const getSelectedCell = (event) => {
    if (template.getSelectedCells) {
      selectedCell = template.getSelectedCells();
      addDiv.addBut.style.display = 'none';
      addDiv.showDiv.style.display = 'block';
    }
    event.stopPropagation();
    event.cancelBubble = true;
    return false;
  }
  function showSelectedCells() {
    if (!selectedCell) {
      if (template.findGroupCells) {
        selectedCell = template.findGroupCells(me.attrData.fieldName);
      }
    }
    if (template.showGroupCells) {
      template.showGroupCells(selectedCell);
    }
  }
  function resetSelectedCells() {
    if (selectedCell) {
      selectedCell = undefined;
      me.attrData.cellInfos = undefined;
      me.attrData.rows = 0;
    }
    addDiv.addBut.style.display = 'inline-block';
    addDiv.showDiv.style.display = 'none';
  }
  function addRow(value) {
    template.addCellsByGroupName(me.fieldName, me.attrData.cellInfos, value);
    count += 1;
    if (count < 2) {
      addDiv.delBut.disabled = false;
    }
  }
  function addBeforeRows() {
    if (template && template.addCellsByGroupName && me.attrData.cellInfos instanceof Array) {
      addRow();
    }
  }
  function delLastRows() {
    if (template && template.delCellsByGroupName) {
      template.delCellsByGroupName(me.fieldName, rows);
      count -= 1;
    }
    if (count == 0) {
      addDiv.delBut.disabled = true;
    }
  }
  this.setDisabled = (arg) => { };
  this.setVisible = (arg) => { };
  this.setReadonly = (arg) => { };
  this.getValue = () => {
    const values = [];
    if (template && template.getGroupComponents) {
      const cells = template.getGroupComponents(me.attrData.fieldName);
      cells.forEach(infos => {
        const temp = {};
        infos.forEach(item => {
          if (item.attrData.fieldName && item.getValue) {
            temp[item.attrData.fieldName] = item.getValue();
          }
        });
        values.push(temp);
      })
    }
    console.log(values)
    return values;
  };
  this.setValue = (arg) => {
    if (arg instanceof Array && arg.length > 0) {
      const cells = template.getGroupComponents(me.attrData.fieldName);
      const value = arg[0];
      cells[0].forEach(item => {
        if (item.attrData.fieldName && item.setValue) {
          item.setValue(value[item.attrData.fieldName]);
        }
      })
      if (template && template.addCellsByGroupName && me.attrData.cellInfos instanceof Array) {
        for (let i = 1; i < arg.length; i += 1) {
          addRow(arg[i]);
        }
      }

    }
  };
  this.reset = () => { };
  // 设置此组件的属性  返回DOcumentNode
  // this.getAttribNode = () => {}
  // 调整本组件的尺寸和位置
  this.sizeChange = () => { };
  this.getAttrData = function () {
    if (selectedCell && selectedCell.length > 0 && template.getGroupCellsInfo) {
      me.attrData.cellInfos = template.getGroupCellsInfo(selectedCell, me.attrData.fieldName);
      me.attrData.rows = me.attrData.cellInfos ? me.attrData.cellInfos.length : 0;
    }
    return me.attrData;
  }
  this.render = () => {
    container.innerHTMML = "";
    if (mode == 1) {
      addDiv.addBut = gkhCreate('button', {
        target: container,
        className: 'gkh-button',
        innerText: '确定选择的单元格',
        style: {
          marginRight: '8px'
        },
        listeners: {
          click: getSelectedCell
        }
      });
      gkhCreate('span', { target: container, childs: [gkhCreate('label', { innerText: '字段名：' }), gkhCreate('input', { attribute: { value: me.fieldName ? me.fieldName : '' }, listeners: { change: fieldNameChange } })] })
      addDiv.showDiv = gkhCreate('div', {
        target: container,
        style: {
          display: 'none',
        },
        childs: [gkhCreate('button', {
          className: 'gkh-button',
          innerText: '查看已选单元格',
          listeners: {
            click: showSelectedCells
          }
        }), gkhCreate('button', {
          className: 'gkh-button',
          innerText: '重选',
          listeners: {
            click: resetSelectedCells
          }
        })]
      });
      if (me.attrData.cellInfos) {
        addDiv.addBut.style.display = 'none';
        addDiv.showDiv.style.display = 'block';
      }
    } else if (mode == 2) {
      addDiv.addBut = gkhCreate('button', {
        target: container,
        className: 'gkh-button',
        innerText: '新增',
        listeners: {
          click: addBeforeRows
        }
      });
      addDiv.delBut = gkhCreate('button', {
        target: container,
        className: 'gkh-button',
        innerText: '删除',
        listeners: {
          click: delLastRows
        }
      });
      addDiv.delBut.disabled = true;
    }
    return container;
  };
  this.renderAfter = () => {

  }
}

function EditTable({ data, onChange, columns, value }) {
  const me = this;
  const container = gkhCreate('gkh-edittable');
  let dataList = data instanceof Array ? data : value;
  if (!dataList) {
    dataList = [];
  }
  dataList.forEach((item, index) => item.itemIndex = index);
  let tbody;
  let editRow;
  let delRow;
  let addRow;
  let renderItem;
  delRow = (item) => {
    const { childNodes } = tbody;
    const index = removeItemInArray(dataList, null, item, 'itemIndex');
    console.log(index);
    tbody.removeChild(childNodes[index]);
  }

  addRow = (record = {}) => {
    dataList.push(record);
    tbody.appendChild(renderItem(record, dataList.length - 1));
  }

  renderItem = (item) => gkhCreate('tr', {
    childs: columns.map(col => {
      if (col.type == 'option') {
        let handles
        if (col.render instanceof Function) {
          handles = col.render(item, { editRow, delRow });
          if (handles && !(handles instanceof Array)) {
            handles = [handles];
          }
        }
        if (!handles) {
          handles = [
            gkhCreate('button', { className: 'gkh-button', innerText: '删除', listeners: { click: () => { delRow(item) } } }),
          ]
        }
        return gkhCreate('td', {
          childs: handles
        })
      }
      if (col.render instanceof Function) {
        let node = col.render(item);
        if (node && !(node instanceof Array)) {
          node = [node];
        }
        return gkhCreate('td', {
          childs: node
        })
      }
      return gkhCreate('td', {
        child: gkhCreate('input', {
          attribute: { value: item[col.dataIndex] ? item[col.dataIndex] : '' }, listeners: {
            change: (event) => {
              item[col.dataIndex] = event.target.value;
              if (onChange) {
                onChange(data, col.dataIndex, event.target.value);
              }
            }
          }
        })
      })
    })
  })

  this.action = {
    editRow,
    delRow,
    addRow
  }

  this.render = () => {
    tbody = gkhCreate('tbody', {
      childs: dataList.map(renderItem)
    })
    gkhCreate('table', {
      target: container,
      className: 'gkh-table',
      attribute: { border: 1 },
      childs: [
        gkhCreate('thead', { child: gkhCreate('tr', { childs: columns.map(item => gkhCreate('th', { innerText: item.title })) }) }),
        tbody
      ]
    })
    gkhCreate('button', { innerText: '新增记录', listeners: { click: () => addRow() }, target: container })
    return container;
  }
  return this;
}

// 下拉框
function Select(attribute = {}, mode = 3, template) {
  const me = this;
  this.type = 6;
  attribute.type = 6;
  this.attrData = attribute;
  this.parentContainer = template;
  const { placeholder = '请选择', defaultValue, disabled, readonly, list } = attribute;
  if (!list) {
    me.attrData.list = [];
  }
  let { value } = attribute;
  let attribDiv;
  if (value === undefined || value === null) {
    value = defaultValue;
  }
  const onChnage = (arg)=>{
    value = arg.target.value;
  }
  let selectNode = undefined;
  if(mode!=1){
    selectNode = gkhCreate('select', {
      attribute: { placeholder, value },
      className: 'gkh-select',
      listeners: { change: onChnage},
      childs: list instanceof Array ? list.map((item) => gkhCreate('option', {
        innerText: item.value,
        attribute: { value: item.key }
      })) : null
    })
  }
  const container = gkhCreate('div', {
    child: selectNode,
  });
  const fieldNameChange = (arg) => {
    me.fieldName = arg.target.value;
  }
  this.setDisabled = (arg) => { };
  this.setVisible = (arg) => { };
  this.setReadonly = (arg) => { };
  this.getValue = () => {
    return value;
  };
  this.setValue = (arg) => {
    value = arg;
    if(selectNode){
      selectNode.value = arg;
    }
  };
  this.reset = () => {
    value = defaultValue;
    selectNode.value = value;
  };
  // 设置此组件的属性  返回DOcumentNode
  this.getAttribNode = () => {
    if (attribDiv) {
      return attribDiv;
    }
    me.dataSourceEdit = new EditTable({ data: me.attrData.list, columns: [{ dataIndex: 'key', title: '键' }, { dataIndex: 'value', title: '值' }, { type: 'option', title: '操作' }] });
    attribDiv = gkhCreate('div', {
      childs: [
        gkhCreate('div', { innerText: '下拉框' }),
        gkhCreate('div', {
          style: { maxHeight: '400px', overflow: 'auto' },
          child: me.dataSourceEdit.render()
        })
      ]
    });
    return attribDiv;
  }
  // 调整本组件的尺寸和位置
  this.sizeChange = () => { };
  this.getAttrData = function () {
    return me.attrData;
  }
  if (mode == 1) {
    gkhCreate('div', { target: container, childs: [gkhCreate('label', { innerText: '字段名：' }), gkhCreate('input', { attribute: { value: me.fieldName ? me.fieldName : '' }, listeners: { change: fieldNameChange } })] })
  }
  this.render = () => {
    return container;
  };
  this.renderAfter = () => {

  }
}

// 模板
function Template(attribute = {}, mode = 3, template) {
  const me = this;
  this.type = 1;
  attribute.type = 1;
  this.attrData = attribute;
  this.parentContainer = template;
  const { placeholder, defaultValue, disabled, readonly } = attribute;
  let { value } = attribute;
  let attribDiv;
  if (value === undefined || value === null) {
    value = defaultValue;
  }
  const container = gkhCreate('div', {});
  const fieldNameChange = (arg) => {
    me.fieldName = arg.target.value;
  }
  this.setDisabled = (arg) => { };
  this.setVisible = (arg) => { };
  this.setReadonly = (arg) => { };
  this.getValue = () => { };
  this.setValue = (arg) => { };
  this.reset = () => { };
  // 设置此组件的属性  返回DOcumentNode
  this.getAttribNode = () => {
    if (attribDiv) {
      return attribDiv;
    }
    attribDiv = gkhCreate('div', {
      childs: [
        gkhCreate('div', { childs: [gkhCreate('label', { innerText: '字段名：' }), gkhCreate('input', { attribute: { value: me.fieldName ? me.fieldName : '' }, listeners: { change: fieldNameChange } })] }),
      ]
    });
    return attribDiv;
  }
  // 调整本组件的尺寸和位置
  this.sizeChange = () => { };
  this.getAttrData = function () {
    return me.attrData;
  }
  this.render = () => {
    return container;
  };
  this.renderAfter = () => {

  }
}

function WordCells() {
  const components = [
    {
      id: 1,
      name: '文本显示框',
      component: TextShow
    },
    {
      id: 2,
      name: '文本输入框',
      component: Textarea
    },
    {
      id: 3,
      name: '表格',
      component: TableTemplate
    },
    {
      id: 5,
      name: '新增按钮',
      component: addButton
    },
    {
      id: 6,
      name: '下拉框',
      component: Select
    },
  ];
  this.addCell = function (arg) {
    if (arg instanceof Object && arg.id) {
      if (id < 20) {
        console.warn('新增单元id已经存在');
        return false;
      }
      const cell = components.find((item) => arg.id === item.id);
      if (cell) {
        console.warn('新增单元id已经存在');
        return false;
      }
      components.push(arg);
    } else {
      console.warn('传入数据格式不对，{id: number; name: string; component: class}');
    }
  }
  this.removeCellById = function (id) {
    const size = components.length - 1;
    let hasRemove = false;
    if (id < 20) {
      return false;
    }
    for (let i = 0; i < components.length; i += 1) {
      if (id === components[i].id) {
        hasRemove = true;
      }
      if (hasRemove && i < size) {
        components[i] = components[i + 1];
      }
    }
    if (hasRemove) {
      components.pop();
    }
    return hasRemove;
  }
  this.removeCellByComponent = function (component) {
    const size = components.length - 1;
    let hasRemove = false;
    for (let i = 0; i < components.length; i += 1) {
      if (component === components[i].component && components[i].id > 20) {
        hasRemove = true;
      }
      if (hasRemove && i < size) {
        components[i] = components[i + 1];
      }
    }
    if (hasRemove) {
      components.pop();
    }
    return hasRemove;
  }
  this.forEach = function (fun) {
    if (fun instanceof Function) {
      components.forEach(fun);
    }
  }
  this.map = function (fun) {
    let arr = [];
    if (fun instanceof Function) {
      arr = components.map(fun);
    }
    return arr;
  }
  this.find = function (id) {
    return components.find((item) => id === item.id);
  }
  let preId;
  let preComponent = TextShow;
  this.getComponent = function (template, mode, attribute = {}) {
    let obj;
    if (attribute.type === undefined) {
      return new TextShow(attribute, mode, template);
    }
    if (preId === attribute.type) {
      return new preComponent(attribute, mode, template);
    }
    const temp = components.find((item) => item.id === attribute.type);
    if (temp) {
      obj = new temp.component(attribute, mode, template);
      preComponent = temp.component;
      preId = attribute.type;
    } else {
      obj = new TextShow(attribute, mode, template);
      preComponent = TextShow;
    }
    return obj;
  }
  return this;
}
const wordCells = new WordCells();

function tableCellType(template, mode, attribute) {
  return wordCells.getComponent(template, mode, attribute);
}
export default WordCells;
export { tableCellType, wordCells };
